package com.xinxin.intelligenceexam.studyMenu.weChatHongBao;

import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Notification;
import android.app.PendingIntent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;

import com.orhanobut.logger.Logger;

import java.util.ArrayList;
import java.util.List;

/**
 * AccessibilityService是一个后台监控服务，当你监控的内容发生改变时，就会调用后台服务的回调方法
 * 通过AccessibilityEvent接收指定事件的回调
 * <br/>
 * 下面是对AccessibilityService中常用的方法的介绍
 * <p>
 * disableSelf()：禁用当前服务，也就是在服务可以通过该方法停止运行
 * findFoucs(int falg)：查找拥有特定焦点类型的控件
 * getRootInActiveWindow()：如果配置能够获取窗口内容,则会返回当前活动窗口的根结点
 * getSeviceInfo()：获取当前服务的配置信息
 * onAccessibilityEvent(AccessibilityEvent event)：有关AccessibilityEvent事件的回调函数，系统通过sendAccessibiliyEvent()不断的发送AccessibilityEvent到此处
 * performGlobalAction(int action)：执行全局操作，比如返回，回到主页，打开最近等操作
 * setServiceInfo(AccessibilityServiceInfo info)：设置当前服务的配置信息
 * getSystemService(String name)：获取系统服务
 * onKeyEvent(KeyEvent event)：如果允许服务监听按键操作，该方法是按键事件的回调，需要注意，这个过程发生了系统处理按键事件之前
 * onServiceConnected()：系统成功绑定该服务时被触发，也就是当你在设置中开启相应的服务，系统成功的绑定了该服务时会触发，通常我们可以在这里做一些初始化操作
 * onInterrupt()：服务中断时的回调
 */

/**
 * 收到微信红包的推送信息，在推送信息中判断是否出现”[微信红包]”的消息提示，如果出现则点击进入聊天界面
 * 通过遍历窗口树节点，发现带有”领取红包”字样的节点，则点击进入，即红包，弹出抢红包界面
 * 在抢红包界面，通过ID获取”开”按钮的节点，则打开红包
 * 在红包详情页面，通过ID获取返回键按钮的节点，点击并返回微信聊天界面
 * 我的手机：开--com.tencent.mm:id/bg7
 * 返回按钮:com.tencent.mm:id/gd
 */
public class AirAccessibilityService extends AccessibilityService {
    public static boolean ALL = false;
    private List<AccessibilityNodeInfo> parents;

    public AirAccessibilityService() {
    }

    /**
     * 当启动服务的时候就会被调用
     */
    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        ALL = true;
        parents = new ArrayList<>();
    }

    /**
     * 监听窗口变化的回调
     */
    /*AccessibilityEvent的方法
    getEventType()：事件类型
    getSource()：获取事件源对应的结点信息
    getClassName()：获取事件源对应类的类型，比如点击事件是有某个Button产生的，那么此时获取的就是Button的完整类名
    getText()：获取事件源的文本信息，比如事件是有TextView发出的,此时获取的就是TextView的text属性。如果该事件源是树结构，那么此时获取的是这个树上所有具有text属性的值的集合
    isEnabled()：事件源(对应的界面控件)是否处在可用状态
    getItemCount()：如果事件源是树结构，将返回该树根节点下子节点的数量*/
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        int eventType = event.getEventType();
        //根据事件回调类型进行处理
        switch (eventType) {
            //当通知栏发生改变时
            case AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED:
                List<CharSequence> texts = event.getText();
                if (!texts.isEmpty()) {
                    for (CharSequence text : texts) {
                        String content = text.toString();
                        if (content.contains("[微信红包]")) {
                            //模拟打开通知栏消息，即打开微信
                            if (event.getParcelableData() != null && event.getParcelableData() instanceof Notification) {
                                Notification notification = (Notification) event.getParcelableData();
                                PendingIntent pendingIntent = notification.contentIntent;
                                try {
                                    pendingIntent.send();
                                    Logger.d("进入微信");
                                } catch (PendingIntent.CanceledException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
                break;
            //当窗口的状态发生改变时
            case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
                String className = event.getClassName().toString();
                if (className.equals("com.tencent.mm.ui.LauncherUI")) {
                    //点击最后一个红包
                    Logger.d("点击红包");
                    getLastPacket();
                } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyReceiveUI")) {
                    //开红包
                    Logger.d("开红包");
                    inputClick("com.tencent.mm:id/bg7");
                } else if (className.equals("com.tencent.mm.plugin.luckymoney.ui.LuckyMoneyDetailUI")) {
                    //退出红包
                    Logger.d("退出红包");
                    inputClick("com.tencent.mm:id/gd");
                }
               /* //获取窗口节点（根节点）
                AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
                //获取指定子节点（控件节点）
                //通过文本找到对应的节点集合
                List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByText(text);
                //通过控件ID找到对应的节点集合，如com.tencent.mm:id/gd
                List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(clickId);
                //模拟点击
                accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                //模拟长按
                accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
                //模拟获取焦点
                accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
                //模拟粘贴
                accessibilityNodeInfo.performAction(AccessibilityNodeInfo.ACTION_PASTE);*/

                break;
        }
    }

    /**
     * 获取list中最后一个红包，并进行模拟点击
     */
    private void getLastPacket() {
        AccessibilityNodeInfo rootNode = getRootInActiveWindow();
        recycle(rootNode);
        if (parents.size() > 0) {
            //如果最后一个还存在，则说明是红包结点，要模拟点击
            parents.get(parents.size() - 1).performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }

    /**
     * 递归函数，遍历每一个节点，并将含有“领取红包”存进List中
     *
     * @param info
     */
    private void recycle(AccessibilityNodeInfo info) {
        if (info.getChildCount() == 0) {
            if (info.getText() != null) {
                if ("领取红包".equals(info.getText().toString())) {
                    if (info.isClickable()) {
                        info.performAction(AccessibilityNodeInfo.ACTION_CLICK);
                    }
                    AccessibilityNodeInfo parent = info.getParent();
                    while (parent != null) {
                        if (parent.isClickable()) {
                            parents.add(parent);
                            break;
                        }
                        parent = parent.getParent();
                    }
                }
            }
        } else {
            for (int i = 0; i < info.getChildCount(); i++) {
                recycle(info.getChild(i));
            }
        }
    }


    /**
     * 通过ID获取控件，并进行模拟点击
     *
     * @param clickId
     */
    private void inputClick(String clickId) {
        AccessibilityNodeInfo nodeInfo = getRootInActiveWindow();
        if (nodeInfo != null) {
            final List<AccessibilityNodeInfo> list = nodeInfo.findAccessibilityNodeInfosByViewId(clickId);
            for (AccessibilityNodeInfo item : list) {
                item.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }

    }

    /**
     * 中断服务的回调
     */
    @Override
    public void onInterrupt() {
        ALL = false;
    }

    private void settingAccessibilityInfo() {
        String[] packageNames = {"com.tencent.mm"};
        AccessibilityServiceInfo mAccessibilityServiceInfo = new AccessibilityServiceInfo();
        // 响应事件的类型，这里是全部的响应事件（长按，单击，滑动等）
        mAccessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
        // 反馈给用户的类型，这里是语音提示
        mAccessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
        // 过滤的包名
        mAccessibilityServiceInfo.packageNames = packageNames;
        setServiceInfo(mAccessibilityServiceInfo);
    }

}
